package com.bbex.service.impl;

import com.bbex.constant.Constants;
import com.bbex.exception.PlatException;
import com.bbex.mapper.CoinVolumeDao;
import com.bbex.mapper.ShareDao;
import com.bbex.pojo.ResponsePage;
import com.bbex.service.DictService;
import com.bbex.service.ShareService;
import com.bbex.util.SnowFlake;
import com.bbex.vo.UserStatisticsInfoVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ShareServiceImpl implements ShareService {

    private static final Logger logger = LoggerFactory.getLogger(ShareServiceImpl.class);

    @Autowired
    private ShareDao shareDao;

    @Autowired
    private DictService dictService;

    @Autowired
    private CoinVolumeDao coinVolumeDao;

    @Override
    public Map getShareMessage() {
        List<Map> tierList = dictService.getDictDetailByItemCode("tier");
        List<Map> shareNumList = dictService.getDictDetailByItemCode("ethNum");
        List<Map> serNumList = dictService.getDictDetailByItemCode("serVolume");
        int tierNum = Integer.valueOf(tierList.get(0).get("dictName").toString());
        int shaerNum = Integer.valueOf(shareNumList.get(0).get("dictName").toString());

        Map map = new HashMap();
        //查询已兑换数量
        BigDecimal totalCount = shareDao.totalCount();
        //层级计算
        int tier = (totalCount.intValue() / shaerNum) + 1;
        //所剩数量
        BigDecimal num = new BigDecimal(shaerNum).multiply(new BigDecimal(tier)).subtract(totalCount);
        //兑换比例
        int scaleInit = tierNum - (totalCount.intValue() / shaerNum);
        int scale = scaleInit > 0 ? scaleInit : 1;
        //矿工费
        BigDecimal serNum = new BigDecimal(serNumList.get(0).get("dictName").toString());

        map.put("totalCount", totalCount);
        map.put("tier", tier);
        map.put("num", num);
        map.put("serNum", serNum);
        map.put("scale", scale);
        return map;
    }

    //共享兑换逻辑
    @Override
    @Transactional
    public synchronized void convelShare(String mobile, String mail, String hmId, String ethId, String userId, BigDecimal ethVolume, BigDecimal serVloume) {
        logger.info("共享兑换开始");
        List<Map> tierList = dictService.getDictDetailByItemCode("tier");
        List<Map> shareNumList = dictService.getDictDetailByItemCode("ethNum");
        int tierNum = Integer.valueOf(tierList.get(0).get("dictName").toString());
        int shaerNum = Integer.valueOf(shareNumList.get(0).get("dictName").toString());
        List<Map> serNumList = dictService.getDictDetailByItemCode("serVolume");
        //矿工费
        BigDecimal serNum = new BigDecimal(serNumList.get(0).get("dictName").toString());
        //查询已兑换数量
       BigDecimal totalCount = shareDao.totalCount();
        logger.info("查询已兑换数量" + totalCount);
        //层级
        int tier = (totalCount.intValue() / shaerNum) + 1;
        //所剩数量
        BigDecimal num = new BigDecimal(shaerNum).multiply(new BigDecimal(tier)).subtract(totalCount);
        //兑换比例
        int scaleInit = tierNum - (totalCount.intValue() / shaerNum);
        int scale = scaleInit > 0 ? scaleInit : 1;
        logger.info("当前兑换比例为" + scale);
        if (num.compareTo(ethVolume) > -1) {
            int multiple = shareVolume(scale);
            BigDecimal hmVolume = ethVolume.multiply(new BigDecimal(scale));
            BigDecimal shareHMVolume = hmVolume.multiply(new BigDecimal(multiple));
            String volume = ethVolume.add(serNum).toString();
            logger.info("更新用户ETH持币量开始,用户id为" + userId + ",更新币种量为" + volume + "");
            int ethCount = coinVolumeDao.updateByethCoinId(ethId, volume, userId);
            if (ethCount < 1) {
                throw new PlatException(Constants.update_ERROR, "更新用户ETH持币量失败!");
            }
            volumeOperation(mobile, mail, hmId, ethId, userId, ethVolume, shareHMVolume, serNum, scale, multiple);
        } else {
            int multiple = shareVolume(scale);
            BigDecimal hmVolume = num.multiply(new BigDecimal(scale));
            BigDecimal shareHMVolume = hmVolume.multiply(new BigDecimal(multiple));
            BigDecimal surpETHVolume = ethVolume.subtract(num);
            volumeOperation(mobile, mail, hmId, ethId, userId, num, shareHMVolume, serNum, scale, multiple);
            int surpScale = (scale - 1) > 0 ? scale - 1 : 1;
            int surpMultiple = shareVolume(surpScale);
            BigDecimal hmVolume1 = surpETHVolume.multiply(new BigDecimal(surpScale));
            BigDecimal surpHMVolume = hmVolume1.multiply(new BigDecimal(surpMultiple));
            String volume = ethVolume.add(serNum).toString();
            logger.info("更新用户ETH持币量开始,用户id为" + userId + ",更新币种量为" + volume + "");
            int ethCount = coinVolumeDao.updateByethCoinId(ethId, volume, userId);
            if (ethCount < 1) {
                throw new PlatException(Constants.update_ERROR, "更新用户ETH持币量失败!");
            }
            volumeOperation(mobile, mail, hmId, ethId, userId, surpETHVolume, surpHMVolume, serNum, surpScale, surpMultiple);

        }

    }

    //添加数据至记录表并更新币库表
    @Transactional
    public int volumeOperation(String mobile, String mail, String hmId, String ethId, String userId, BigDecimal ethVolume, BigDecimal hmVolume, BigDecimal serviceVolume, int scale, int multiple) {
        logger.info("查询用户HMC持币量");
        List<Map> list = coinVolumeDao.getCoinInfo(hmId, userId);
        if (list != null && !list.isEmpty()) {
            logger.info("更新用户HMC持币量开始,用户id为" + userId + ",更新币种量为" + hmVolume + "");
            int hmCount = coinVolumeDao.updateByhmCoinId(hmId, hmVolume.toString(), userId);
            if (hmCount < 1) {
                throw new PlatException(Constants.update_ERROR, "更新用户HMC持币量失败!");
            }
        } else {
            Map map = new HashMap();
            String id = SnowFlake.createSnowFlake().nextIdString();
            String coinSymbol = coinVolumeDao.findCoinSybolByid(hmId);
            map.put("id", id);
            map.put("userId", userId);
            map.put("hmId", hmId);
            map.put("coinSymbol", coinSymbol);
            map.put("hmVolume", hmVolume);
            map.put("cerateTime", new Date());
            logger.info("用户无HMC,添加HMC数据至用户持币量表");
            int insertHmCount = coinVolumeDao.insert(map);
            if (insertHmCount < 1) {
                throw new PlatException(Constants.update_ERROR, "添加用户HMC持币量失败!");
            }
        }
        Map logMap = new HashMap();
        String id = SnowFlake.createSnowFlake().nextIdString();
        String coinSymbol = coinVolumeDao.findCoinSybolByid(ethId);
        logMap.put("id", id);
        logMap.put("type", "1");
        logMap.put("userId", userId);
        logMap.put("mobile", mobile);
        logMap.put("mail", mail);
        logMap.put("coinId", ethId);
        logMap.put("coinSymbol", coinSymbol);
        logMap.put("ethVolume", ethVolume);
        logMap.put("hmVolume", hmVolume);
        logMap.put("serviceVolume", serviceVolume);
        logMap.put("scale", scale);
        logMap.put("multiple", multiple);
        logMap.put("createDate", new Date());
        logMap.put("status", "1");
        logger.info("添加用户分享兑换记录，参数为" + logMap.toString());
        int insertLog = coinVolumeDao.insertLog(logMap);
        if (insertLog < 1) {
            throw new PlatException(Constants.update_ERROR, "添加用户分享兑换记录失败!");
        }
        return insertLog;
    }


    //兌換等級公共方法
    public int shareVolume(int scale) {
        int level1 = Integer.valueOf(dictService.getDictListByItemCode("converLevel", "level1").get("dictName").toString());
        int level2 = Integer.valueOf(dictService.getDictListByItemCode("converLevel", "level2").get("dictName").toString());
        int level3 = Integer.valueOf(dictService.getDictListByItemCode("converLevel", "level3").get("dictName").toString());
        int level4 = Integer.valueOf(dictService.getDictListByItemCode("converLevel", "level4").get("dictName").toString());

        if (900 < scale && scale <= 1000) {
            return level1;
        }
        if (800 < scale && scale <= 900) {
            return level2;
        }
        if (700 < scale && scale <= 800) {
            return level3;
        } else {
            return level4;
        }

    }


    @Override
    public List<Map> getRankInfo() {
        BigDecimal totalVolume=BigDecimal.ZERO;
        Date time = new Date();
        Map map = coinVolumeDao.findTime(time);
        if(map!=null && !map.isEmpty()){
        Date startTime= (Date) map.get("startTime");
        Date endTime=(Date)map.get("endTime");
        List <Map> list=coinVolumeDao.findRankLog(startTime,endTime);
            for (int i = 0; i <list.size(); i++) {
                BigDecimal volume=new BigDecimal(list.get(i).get("volume").toString());
                totalVolume=totalVolume.add(volume);
            }
            for (int i = 0; i <list.size() ; i++) {
                BigDecimal volume=new BigDecimal(list.get(i).get("volume").toString());
                BigDecimal scale=volume.divide(totalVolume,4,BigDecimal.ROUND_HALF_UP);
                String scalely=scale.multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_HALF_UP).toString()+"%";
                list.get(i).put("scalely",scalely);
            }
            return list;
        }else {
            return null;
        }
    }


    @Override
    /**
    * 查看个人共享兑换记录
    * @author      wangyayun
    * @param infoVO
    * @return      java.util.List<java.util.Map>
    * @exception
    * @date        2019/8/31 13:59
    */
    public ResponsePage<Map> getPersonRankInfo(UserStatisticsInfoVO infoVO) {
        String userId=infoVO.getUserId();
        ResponsePage<Map> responsePage = new ResponsePage<>();
        Page<Map> page = PageHelper.startPage(infoVO.getCurrentPage(), infoVO.getShowCount());
       List<Map> data = shareDao.getPersonRankInfo(userId);
        responsePage.setCount(page.getTotal());
       responsePage.setList(data);
        return responsePage;
    }
}
